<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        /* 
The comments here attempt to explain the implementations of spritesheet animations in Danger Crew.

We'll utilize a dynamic "pixel size" which will allow us to upscale the pixel art in even multiplications.
EX: if an asset is designed as a 10px by 10px square, we can multiply by pixel size of 4 to enlarge the asset to 40px by 40px. This value can be adjusted per screen real estate. 
*/

        :root {
            --pixel-size: 4;
            /* Try playing with this value! */
        }


        /* 
   Allow pixel art images and canvas tags to scale up without losing quality
*/
        .PixelArtImage {
            image-rendering: -moz-crisp-edges;
            image-rendering: -webkit-crisp-edges;
            image-rendering: pixelated;
            image-rendering: crisp-edges;
        }


        /* 
	This is the square crop of the character, each frame designed at natural size 32x32. 
	Multiplied by dynamic pixel size.
*/
        .Character {
            width: calc(var(--pixel-size) * 32px);
            height: calc(var(--pixel-size) * 32px);
            overflow: hidden;
            position: relative;
            margin: calc(var(--pixel-size) * 6px) auto;
        }

        .Character_shadow {
            width: calc(var(--pixel-size) * 32px);
            height: calc(var(--pixel-size) * 32px);
            opacity: 0.25;
            position: absolute;
        }

        /* Set up a CSS Animation to move our spritesheet to the LEFT. */
        @keyframes walkAnimation {
            from {
                transform: translate3d(0%, 0%, 0);
            }

            to {
                transform: translate3d(-100%, 0%, 0);
            }
        }

        /* 
	One spritesheet containing layout of 4 by 4 frames, each designed at 32x32.
	Total width = 128px multiplied by dynamic pixel size.
	The visible part is cropped out via .Character's overflow:hidden rule. This image lives *inside* the .Character container.
*/
        .Character_sprite-sheet {
            width: calc(var(--pixel-size) * 128px);
            animation: walkAnimation 0.6s steps(4) infinite;
            /* ^ "Complete the animation in 4 distinct steps". We use 4 because each row of the spritesheet has 4 frames. */
            position: absolute;
            top: 0;
            left: 0;

            display: none;
            /* For the sake of this demo, JS will control which character spritesheet is visible */
        }

        .Character_sprite-sheet.active {
            display: block;
        }

        /* 
	Set up classes that change the y position of underlying spritesheet.
	Spritesheet is designed with this layout:
		D1 D2 D3 D4
		R1 R2 R3 R4 (32px away from top)
		U1 U2 U3 U4 (64px away from top)
		L1 L2 L3 L4 (96px away from top)

   EX: https://s3-us-west-2.amazonaws.com/s.cdpn.io/21542/WalkingDemo-HANK-2-SHEET.png
*/

        .Character--walk-down .Character_sprite-sheet {
            top: 0;
        }

        .Character--walk-right .Character_sprite-sheet {
            top: calc(var(--pixel-size) * -32px);
        }

        .Character--walk-up .Character_sprite-sheet {
            top: calc(var(--pixel-size) * -64px);
        }

        .Character--walk-left .Character_sprite-sheet {
            top: calc(var(--pixel-size) * -96px);
        }


        /* Demo UI Stuff ------------------------------------------------- */
        * {
            box-sizing: border-box;
        }

        body {
            margin: 0;
            padding: 0;
            background-image: linear-gradient(180deg, #5DCBE4 0%, #47BCE4 100%);
            height: 100%;
            min-height: 100vh;
            padding-top: calc(var(--pixel-size) * 18px);
            font-family: 'Dosis', sans-serif;
        }

        .Container {
            max-width: calc(var(--pixel-size) * 100px);
            margin: 0 auto;
        }

        .TitleImage {
            width: calc(var(--pixel-size) * 95px);
            display: block;
            margin: 0 auto;
        }

        .NavigationBubble {
            -webkit-appearance: none;
            width: calc(var(--pixel-size) * 3px);
            height: calc(var(--pixel-size) * 3px);
            background: #2497cc;
            border: 0;
            outline: 0;
            cursor: pointer;
            padding: 0;
            margin-left: 0.5em;
            margin-right: 0.5em;
            box-sizing: content-box;
        }

        .NavigationBubble:hover:not(.active) {
            opacity: 0.9;
        }

        .NavigationBubble.active {
            background: #fff;
        }

        .NextSpritesheetButton {
            -webkit-appearance: none;
            border: 0;
            background: none;
            padding: 1em;
            position: absolute;
            top: 50%;
        }

        .NextSpritesheetButton--prev {
            left: 0;
        }

        .NextSpritesheetButton--next {
            right: 0;
        }

        .NextSpritesheetButton:hover {
            cursor: pointer;
            background: rgba(255, 255, 255, 0.2);
        }

        .NextSpritesheetButton:focus {
            outline: none;
        }

        .NextSpritesheetButton svg {
            display: block;
            width: calc(var(--pixel-size) * 4px);
        }

        .DirectionArrow {
            background: none;
            outline: 0;
            border: 0;
            cursor: pointer;
        }

        .DirectionArrow svg {
            display: block;
            width: calc(var(--pixel-size) * 13px);
        }

        .DirectionArrow--active .Arrow_outline-top {
            stroke: #5268ec;
        }

        .DirectionArrow--active .Arrow_surface {
            stroke: #639bff;
        }

        .DirectionArrow--active .Arrow_outline-bottom {
            stroke: #164496;
        }

        .DirectionArrow--active .Arrow_edge {
            stroke: #7baaff;
        }

        .DirectionArrow--active .Arrow_front {
            stroke: #4c8bfd
        }

        .DirectionArrow--active .Arrow_arrow-inset {
            stroke: #fff;
        }

        .DirectionArrow--active .Arrow_arrow-body {
            stroke: #fff;
        }

        .SpritesheetSlider {
            position: relative;
            margin-bottom: calc(var(--pixel-size) * 10px);
        }

        .flex-center {
            display: flex;
            justify-content: center;
        }

        footer {
            margin-top: calc(var(--pixel-size) * 20px);
        }

        @media (min-height: 515px) {
            footer {
                position: absolute;
                left: 0;
                right: 0;
                bottom: 0;
            }
        }

        footer p {
            color: #fff;
            text-align: center;
            padding: 0.8em;
            font-size: 18px;
            margin: 0;
            border-top: 1px solid rgba(255, 255, 255, 0.4)
        }

        footer a {
            font-weight: bold;
            font-size: 18px;
            color: #164496;
        }
    </style>
</head>

<body>
    <main class="Container">
        <img class="TitleImage PixelArtImage"
            src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/21542/WalkingDemo-WalkingSprites.png"
            alt="Walking Demo Sprites" />
        <div class="SpritesheetSlider">


            <!-- This div is our character -->
            <div class="Character Character--walk-down">
                <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/21542/WalkingDemo-Shadow.png"
                    class="Character_shadow PixelArtImage" />
                <!-- Spritesheets injected here: -->
            </div>




            <div class="Navigation flex-center">
                <!-- Navigation bubbles injected here: -->
            </div>
            <button class="NextSpritesheetButton NextSpritesheetButton--prev" onclick="setPreviousActive()">
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -0.5 4 7" shape-rendering="crispEdges">
                    <metadata>Made with Pixels to Svg https://codepen.io/shshaw/pen/XbxvNj</metadata>
                    <path stroke="#434343" d="M3 0h1M2 1h1M1 2h1M0 3h1M1 4h1M2 5h1M3 6h1" />
                </svg>
            </button>
            <button class="NextSpritesheetButton NextSpritesheetButton--next" onclick="setNextActive()">
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -0.5 4 7" shape-rendering="crispEdges">
                    <metadata>Made with Pixels to Svg https://codepen.io/shshaw/pen/XbxvNj</metadata>
                    <path stroke="#434343" d="M0 0h1M1 1h1M2 2h1M3 3h1M2 4h1M1 5h1M0 6h1" />
                </svg>
            </button>
        </div>
        <div class="DemoDirectionUI flex-center">
            <button class="DirectionArrow DirectionArrow-left" onclick="setDirection('LEFT')">
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -0.5 13 13" shape-rendering="crispEdges">
                    <path class="Arrow_outline-top" stroke="#5f5f5f"
                        d="M1 0h11M0 1h1M12 1h1M0 2h1M12 2h1M0 3h1M12 3h1M0 4h1M12 4h1M0 5h1M12 5h1M0 6h1M12 6h1M0 7h1M12 7h1M0 8h1M12 8h1" />
                    <path class="Arrow_surface" stroke="#f5f5f5"
                        d="M1 1h11M1 2h11M1 3h5M7 3h5M1 4h4M7 4h5M1 5h3M7 5h5M1 6h4M7 6h5M1 7h5M7 7h5M1 8h11" />
                    <path class="Arrow_arrow-inset" stroke="#434343" d="M6 3h1M5 4h1M4 5h1" />
                    <path class="Arrow_arrow-body" stroke="#5f5f5f" d="M6 4h1M5 5h2M5 6h2M6 7h1" />
                    <path class="Arrow_outline-bottom" stroke="#434343"
                        d="M0 9h1M12 9h1M0 10h1M12 10h1M0 11h1M12 11h1M1 12h11" />
                    <path class="Arrow_edge" stroke="#ffffff" d="M1 9h11" />
                    <path class="Arrow_front" stroke="#cccccc" d="M1 10h11M1 11h11" />
                </svg>
            </button>
            <button class="DirectionArrow DirectionArrow-up" onclick="setDirection('UP')">
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -0.5 13 13" shape-rendering="crispEdges">
                    <path class="Arrow_outline-top" stroke="#5f5f5f"
                        d="M1 0h11M0 1h1M12 1h1M0 2h1M12 2h1M0 3h1M12 3h1M0 4h1M12 4h1M0 5h1M12 5h1M0 6h1M12 6h1M0 7h1M12 7h1M0 8h1M12 8h1" />
                    <path class="Arrow_surface" stroke="#f5f5f5"
                        d="M1 1h11M1 2h11M1 3h11M1 4h5M7 4h5M1 5h4M8 5h4M1 6h3M9 6h3M1 7h11M1 8h11" />
                    <path class="Arrow_arrow-inset" stroke="#434343" d="M6 4h1M5 5h1M7 5h1" />
                    <path class="Arrow_arrow-body" stroke="#5f5f5f" d="M6 5h1M4 6h5" />
                    <path class="Arrow_outline-bottom" stroke="#434343"
                        d="M0 9h1M12 9h1M0 10h1M12 10h1M0 11h1M12 11h1M1 12h11" />
                    <path class="Arrow_edge" stroke="#ffffff" d="M1 9h11" />
                    <path class="Arrow_front" stroke="#cccccc" d="M1 10h11M1 11h11" />
                </svg>
            </button>
            <button class="DirectionArrow DirectionArrow-down DirectionArrow--active" onclick="setDirection('DOWN')">
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -0.5 13 13" shape-rendering="crispEdges">
                    <path class="Arrow_outline-top" stroke="#5f5f5f"
                        d="M1 0h11M0 1h1M12 1h1M0 2h1M12 2h1M0 3h1M12 3h1M0 4h1M12 4h1M0 5h1M12 5h1M0 6h1M12 6h1M0 7h1M12 7h1M0 8h1M12 8h1" />
                    <path class="Arrow_surface" stroke="#f5f5f5"
                        d="M1 1h11M1 2h11M1 3h11M1 4h3M9 4h3M1 5h4M8 5h4M1 6h5M7 6h5M1 7h11M1 8h11" />
                    <path class="Arrow_arrow-inset" stroke="#434343" d="M4 4h5" />
                    <path class="Arrow_arrow-body" stroke="#5f5f5f" d="M5 5h3M6 6h1" />
                    <path class="Arrow_outline-bottom" stroke="#434343"
                        d="M0 9h1M12 9h1M0 10h1M12 10h1M0 11h1M12 11h1M1 12h11" />
                    <path class="Arrow_edge" stroke="#ffffff" d="M1 9h11" />
                    <path class="Arrow_front" stroke="#cccccc" d="M1 10h11M1 11h11" />
                </svg>
            </button>
            <button class="DirectionArrow DirectionArrow-right" onclick="setDirection('RIGHT')">
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -0.5 13 13" shape-rendering="crispEdges">
                    <path class="Arrow_outline-top" stroke="#5f5f5f"
                        d="M1 0h11M0 1h1M12 1h1M0 2h1M12 2h1M0 3h1M12 3h1M0 4h1M12 4h1M0 5h1M12 5h1M0 6h1M12 6h1M0 7h1M12 7h1M0 8h1M12 8h1" />
                    <path class="Arrow_surface" stroke="#f5f5f5"
                        d="M1 1h11M1 2h11M1 3h5M7 3h5M1 4h5M8 4h4M1 5h5M9 5h3M1 6h5M8 6h4M1 7h5M7 7h5M1 8h11" />
                    <path class="Arrow_arrow-inset" stroke="#434343" d="M6 3h1M7 4h1M8 5h1" />
                    <path class="Arrow_arrow-body" stroke="#5f5f5f" d="M6 4h1M6 5h2M6 6h2M6 7h1" />
                    <path class="Arrow_outline-bottom" stroke="#434343"
                        d="M0 9h1M12 9h1M0 10h1M12 10h1M0 11h1M12 11h1M1 12h11" />
                    <path class="Arrow_edge" stroke="#ffffff" d="M1 9h11" />
                    <path class="Arrow_front" stroke="#cccccc" d="M1 10h11M1 11h11" />
                </svg>
            </button>
        </div>
    </main>
    <footer>
        <p>Characters from <a href="https://store.steampowered.com/app/1064690/Danger_Crew?icid=codepenwalkingdemo"
                target="_blank">Danger Crew</a>, an RPG about being a programmer!
    </footer>

    <script>

        //This stuff just makes the demo's UI work. ---------------
        var characterElement = document.querySelector(".Character");

        var spritesheets = [
            "https://s3-us-west-2.amazonaws.com/s.cdpn.io/21542/WalkingDemo-HANK-2-SHEET.png",
            "https://s3-us-west-2.amazonaws.com/s.cdpn.io/21542/WalkingDemo-EMMY-SHEET.png",
            "https://s3-us-west-2.amazonaws.com/s.cdpn.io/21542/WalkingDemo-SHIRMOND-SHEET.png",
            "https://s3-us-west-2.amazonaws.com/s.cdpn.io/21542/WalkingDemo-SARA-SHEET.png",
            "https://s3-us-west-2.amazonaws.com/s.cdpn.io/21542/WalkingDemo-PATTY-SHEET.png",
            "https://s3-us-west-2.amazonaws.com/s.cdpn.io/21542/WalkingDemo-JESSIE-SHEET.png",
            "https://s3-us-west-2.amazonaws.com/s.cdpn.io/21542/WalkingDemo-KIM-SHEET.png",
            "https://s3-us-west-2.amazonaws.com/s.cdpn.io/21542/WalkingDemo-MINDY-SHEET.png",
            "https://s3-us-west-2.amazonaws.com/s.cdpn.io/21542/WalkingDemo-ZAK-SHEET.png",
            "https://s3-us-west-2.amazonaws.com/s.cdpn.io/21542/WalkingDemo-BEAR-SHEET.png",
        ];

        let activeIndex = 0;
        let spritesheetElements = "";
        let navigationElements = "";


        spritesheets.forEach((spritesheet, index) => {
            spritesheetElements += `<img src="${spritesheet}" class="PixelArtImage Character_sprite-sheet index-${index}" />`
            navigationElements += `<button class="NavigationBubble index-${index}" onclick='setActive(${index})' />`
        });
        characterElement.insertAdjacentHTML('beforeend', spritesheetElements);

        document.querySelector(".Navigation").insertAdjacentHTML('beforeend', navigationElements);

        function setActive(index) {
            activeIndex = index;
            document.querySelectorAll(`.active`).forEach(node => {
                node.classList.remove("active")
            })
            document.querySelectorAll(`.index-${index}`).forEach(node => {
                node.classList.add("active")
            })
        }

        function setDirection(direction) {
            [
                "Character--walk-down",
                "Character--walk-right",
                "Character--walk-up",
                "Character--walk-left"
            ].forEach(className => {
                characterElement.classList.remove(className)
            })


            document.querySelector(".DirectionArrow--active").classList.remove("DirectionArrow--active")

            var directionClass = "Character--walk-down";
            if (direction === "DOWN") {
                document.querySelector(".DirectionArrow-down").classList.add("DirectionArrow--active")
            }

            if (direction === "LEFT") {
                directionClass = "Character--walk-left"
                document.querySelector(".DirectionArrow-left").classList.add("DirectionArrow--active")
            }
            if (direction === "RIGHT") {
                directionClass = "Character--walk-right"
                document.querySelector(".DirectionArrow-right").classList.add("DirectionArrow--active")
            }
            if (direction === "UP") {
                directionClass = "Character--walk-up"
                document.querySelector(".DirectionArrow-up").classList.add("DirectionArrow--active")
            }

            characterElement.classList.add(directionClass)
        }

        function setPreviousActive() {
            activeIndex = activeIndex > 0 ? activeIndex - 1 : spritesheets.length - 1;
            setActive(activeIndex)
        }

        function setNextActive() {
            activeIndex = activeIndex < spritesheets.length - 1 ? activeIndex + 1 : 0;
            setActive(activeIndex)
        }

        //Kick it off!
        setActive(activeIndex);
    </script>
</body>

</html>